/**
 * [1 Timothy 3:16-17 ESV]
 * All Scripture is breathed out by God and profitable
 * for teaching, for reproof, for correction, and for training in righteousness,
 * that the man of God may be complete, equipped for every good work.
 *
 * BibleReader is an simple application for you to study God's Word.
 * The main user of this application maybe the pastor who's main language
 * is Chinese Simplified.
 *
 * You can use it totally free, and if you want to get source code of
 * this application, please email me at dweng123@gmail to get the source
 * code.
 *
 */

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QList>
#include <QMessageBox>
#include <QLineEdit>
#include "time.h"
#include "biblereaderhtmldelegate.h"
#include "bibleverse.h"
#include "biblesearchwidget.h"

// for logging
#include "Logger.h"

BibleSearchWidget::BibleSearchWidget(BibleReaderCore *brc, QWidget *parent) :
    QWidget(parent)
{
    brCore = brc;
    connect(brc, SIGNAL(searchRequest(QString)), this, SLOT(searchText(QString)));
    createWidgets();
    doLayout();
}

BibleSearchWidget::~BibleSearchWidget() {
    destoryWidgets();
}

bool BibleSearchWidget::navToChapter(QTreeWidgetItem* current, int column)
{
    if(current->data(2, Qt::DisplayRole).isValid()) {
        QString version = current->data(2, Qt::DisplayRole).toString();
        int book = current->data(3, Qt::DisplayRole).toInt();
        int chapter = current->data(4, Qt::DisplayRole).toInt();
        int verse = current->data(5, Qt::DisplayRole).toInt();

        // emit chapterChanged signal
        brCore->setCurrentBCV(book, chapter, verse);
        brCore->setCurrentVersion(version);
    }

    return true;
}

void BibleSearchWidget::searchText(QString q)
{
    searchInput->setCurrentText(q);
    searchBtn->click();
}



void BibleSearchWidget::doLayout() {
    QVBoxLayout *vLayout = new QVBoxLayout(this);
    QHBoxLayout *hLayout = new QHBoxLayout(this);

    hLayout->addWidget(searchRangeBase, 6);
    hLayout->addWidget(searchInput, 6);
    hLayout->addWidget(searchBtn, 2);
    vLayout->addLayout(hLayout);
    vLayout->addWidget(searchResult);
    setLayout(vLayout);
}

void BibleSearchWidget::createWidgets()
{
    searchInput = new QComboBox(this);
    searchInput->setEditable(true);
    connect(searchInput->lineEdit(), SIGNAL(returnPressed()),
            this, SLOT(getSearchResult()));

    searchBtn = new QPushButton(tr("Search"), this);
    searchBtn->setIcon(QIcon(QString(":/img/assets/images/find.png")));
    connect(searchBtn, SIGNAL(clicked()), this, SLOT(getSearchResult()));

    searchRangeBase = new QComboBox(this);

    QStringList searchScopeTitles;
    searchScopeTitles << tr("All") << tr("Pentateuch") << tr("History")
                      << tr("Wisdom") << tr("Prophets") << tr("Gospels")
                      << tr("Acts") << tr("Paul Epistles") << tr("General Epistles")
                      << tr("Revelation");
    for (int i = 1; i <= 10; i++) {
        searchRangeBase->addItem(searchScopeTitles[i-1], i);
    }

    // search result tree widget
    searchResult = new BibleSearchResultWidget(brCore, this);
    QStringList headers;
    headers << tr("Verse") << tr("Text") << tr("Version") << tr("Book")
            << tr("Chapter") << tr("Verse");
    searchResult->setHeaderLabels(headers);
    searchResult->setColumnHidden(2, true);
    searchResult->setColumnHidden(3, true);
    searchResult->setColumnHidden(4, true);
    searchResult->setColumnHidden(5, true);
    // set item delegate
    searchResult->setItemDelegate(new BibleReaderHTMLDelegate());

    // click widget item signal catch.
    connect(searchResult, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
            this, SLOT(navToChapter(QTreeWidgetItem*, int)));
    connect(searchResult, SIGNAL(fireCmpVerse()), this, SIGNAL(fireVerseCmp()));
}

void BibleSearchWidget::destoryWidgets()
{
    delete searchInput;
    delete searchBtn;
    delete searchRangeBase;
    delete searchResult;
}

void BibleSearchWidget::getSearchResult()
{
    QString q = searchInput->currentText();
    if (q.isEmpty()) return;
    BibleTextDAO::SearchScope scope = static_cast<BibleTextDAO::SearchScope>
    (searchRangeBase->currentData().toInt());
    result = brCore->search(q, scope);

    q = q.replace("<", "&lt;");
    q = q.replace(">", "&gt;");
    QTreeWidgetItem *root = new QTreeWidgetItem();
    int timestamp = time(0);
    root->setData(0, Qt::DisplayRole, QString("[%1:%2]").arg(q, QString::number(result.count())));
    root->setData(1, Qt::UserRole, timestamp);
    searchResult->addResult(timestamp, result);

    QString searchTip = tr("Searched version:<font color=\"blue\">%1</font><br />Query string:<font color=\"blue\">%2</font><br />Count: <font color=\"red\">%3</font>");
    root->setToolTip(0, searchTip.arg(brCore->getCurrentBibleInfo().getFullname(), q, QString::number(result.count())));

    // create old testament node
    QTreeWidgetItem *oldtestament = new QTreeWidgetItem(root);
    QTreeWidgetItem *newtestament = new QTreeWidgetItem(root);
    QMap<int, QTreeWidgetItem *> books;
    QMap<int, int> searchnumbers;
    // create new testament node
    for (int i = 0; i < result.count(); i++) {
        BibleVerse b = result[i];
        if (!books.contains(b.getBookNumber())) {
            int booknum = b.getBookNumber();
            if (booknum <= 39) {
                books.insert(b.getBookNumber(), new QTreeWidgetItem(oldtestament));
                books[b.getBookNumber()]->setData(0, Qt::DisplayRole, b.getBookName().append("[%1]"));
            } else {
                books.insert(b.getBookNumber(), new QTreeWidgetItem(newtestament));
                books[b.getBookNumber()]->setData(0, Qt::DisplayRole, b.getBookName().append("[%1]"));
            }
        }
        // +1 for books search numbers
        if (!searchnumbers.contains(b.getBookNumber())) {
            searchnumbers.insert(b.getBookNumber(), 0);
        }
        searchnumbers[b.getBookNumber()] = searchnumbers[b.getBookNumber()] + 1;

        // create search result item
        QTreeWidgetItem *item = new QTreeWidgetItem(books.value(b.getBookNumber()));
        QString verse = QString("<font color=\"green\">[%1 %2:%3]</font>").arg(b.getBookName(),
                  QString::number(b.getChapter()),
                  QString::number(b.getVerse()));
        // apply verse text shower to QLabel

        item->setData(0, Qt::DisplayRole, verse);
        QString verseText = b.getVerseText();
        verseText = verseText.replace("<", "&lt;");
        verseText = verseText.replace(">", "&gt;");
        QString hilightText =  verseText.replace(q, QString("<font color=\"red\">"+q+"</font>"));
        item->setData(1, Qt::DisplayRole, hilightText);
        item->setData(2, Qt::DisplayRole, b.getBibleVersion());
        item->setData(3, Qt::DisplayRole, b.getBookNumber());
        item->setData(4, Qt::DisplayRole, b.getChapter());
        item->setData(5, Qt::DisplayRole, b.getVerse());
        item->setToolTip(0, verse.append(" ").append(hilightText));
        item->setToolTip(1, verse);
    }

    // update all nodes label
    QMapIterator<int, QTreeWidgetItem*> iter(books);
    int oldtestamentnum = 0;
    int newtestamentnum = 0;
    while (iter.hasNext()) {
        iter.next();
        if (iter.key() <= 39) {
            oldtestamentnum += searchnumbers[iter.key()];
        } else {
            newtestamentnum += searchnumbers[iter.key()];
        }

        iter.value()->setData(0, Qt::DisplayRole,
                              iter.value()->data(0, Qt::DisplayRole).toString().arg(searchnumbers[iter.key()]));
    }
    oldtestament->setData(0, Qt::DisplayRole, tr("Old Testament[%1]").arg(oldtestamentnum));
    newtestament->setData(0, Qt::DisplayRole, tr("New Testament[%1]").arg(newtestamentnum));
    // !end update

    searchResult->addTopLevelItem(root);
}

